import Local from "tools-utils/storage";
import localConfig from "@/config";
import Error404 from "@/views/error/404.vue";
import { dynamicRoutes, notFoundAndNoPower } from "@/router/route";
import { router } from "@/router/index";
import { useLayoutStore } from "element-plus-layout/columns/layout-store";
import { useUserInfoStore } from "@/store/modules/userInfo";

/**
 * 获取目录下的 .vue、.tsx 全部文件
 */
const viewsModules = import.meta.glob("../views/**/*.{vue,tsx}");
const dynamicViewsModules = Object.assign({}, { ...viewsModules });

// 二维数组的路由数据
let routeData = [];

/**
 * 后端控制路由：初始化方法，防止刷新时路由丢失
 * @method NextLoading 界面 loading 动画开始执行
 * @method GetMenus 获取路由菜单数据
 * @method formatMenuData 重组菜单数据格式
 * @method setAddRoute 添加动态路由
 */
export async function initBackEndControlRoutes() {
  // 无 token 停止执行下一步
  if (!Local.get("token")) return Promise.reject(new Error("未登录，请先登录！"));
  // 获取菜单路由和用户权限点
  const [res] = await Promise.all([Api.menu.GetMenuRouter(), useUserInfoStore().GetUserAuths()]);
  // 重组菜单数据格式
  routeData = formatMenuData(res.data || []);
  // 无登录权限时，添加判断
  if (routeData.length <= 0) return Promise.reject(new Error("当前账号无任何权限，请联系管理员！"));
  // 设置默认默认跳转页面
  dynamicRoutes[0].redirect = getDefaultRoute(routeData[0]);
  // 检查路由 name 是否唯一，控制台打印警告
  checkRouteName(routeData);
  // 添加动态路由
  setAddRoute();
  // 设置 layout 布局信息
  setLayoutData();
}

/**
 * 添加动态路由
 * @method router.addRoute
 * @description 此处循环为 dynamicRoutes（/@/router/route）第一个顶级 children 的路由一维数组，非多级嵌套
 * @link 参考：https://next.router.vuejs.org/zh/api/#addroute
 */
export function setAddRoute() {
  dynamicRoutes[0].children = [...routeData, ...notFoundAndNoPower];
  dynamicRoutes.forEach(route => {
    router.addRoute(route);
  });
}

/**
 * 递归检查路由，所有的路由 name 必须唯一
 * @param routes 路由数组
 * @param names 路由 name 数组
 */
export function checkRouteName(routes, names = []) {
  routes.forEach(route => {
    if (names.includes(route.name)) {
      console.warn(`🚀 ~ checkRouteName ~ 重复的路由 name: ${route.name}`);
    } else {
      names.push(route.name);
    }
    if (route.children) {
      checkRouteName(route.children, names);
    }
  });
}

/**
 * 设置 layout 布局信息
 * 左侧菜单、横向菜单、logo、标题
 */
export function setLayoutData() {
  const layoutStore = useLayoutStore();
  layoutStore.setMainAside(routeData);
  layoutStore.setLogo(localConfig.globalLogo);
  layoutStore.setTitle(localConfig.globalTitle);
}

/**
 * 重组菜单数据格式
 */
export function formatMenuData(routes, parentPath = "", level = 1) {
  if (!routes) return;
  return routes.map(item => {
    let route = {
      path: parentPath + checkPath(item.path),
      name: item.name,
      component: item.component,
      redirect: checkPath(item.redirect),
      level: level,
      meta: {
        title: item.meta?.title,
        icon: item.meta?.icon,
        activeIcon: item.meta?.activeIcon,
        keepAlive: item.meta?.keepAlive,
        appCode: item.meta?.appCode,
        authKey: item.meta?.authKey,
        visible: item.meta?.visible,
        isAffix: item.meta?.isAffix,
        fullScreen: item.meta?.fullScreen,
      },
      children: item.children,
    };
    // 动态导入组件
    route.component = dynamicImport(route);
    // 是否有子菜单，并递归处理
    route.children =
      item.children && item.children.length > 0 ? formatMenuData(item.children, checkPath(route.path), level + 1) : [];
    return route;
  });
}

/**
 * 传入一个字符串，检查是否是以 / 开头，不是则加上
 * @param path 路径
 */
export function checkPath(path) {
  if (path && !path.startsWith("/")) return `/${path}`;
  else if (path === "/") return "";
  return path;
}

/**
 * 获取默认第一个路由 path
 * @param route 路由信息
 */
export function getDefaultRoute(route) {
  if (!route) return "/";
  if (route.children && route.children.length > 1) {
    return getDefaultRoute(route.children[0]);
  }
  return `${checkPath(route.path)}` || "/";
}

/**
 * 后端路由 component 转换函数
 * @param route 后端返回的路由
 * @returns 返回 component 处理成函数的路由对象
 */
export function dynamicImport(route) {
  // Layout 组件特殊处理
  if (route.component === "Layout" || !route.component) return null;
  // 正常业务组件
  const keys = Object.keys(dynamicViewsModules);
  const matchKeys = keys.filter(key => {
    const k = key.replace(/..\/views|../, "");
    return k.startsWith(`${route.component}`) || k.startsWith(`/${route.component}`);
  });
  // 匹配到多个时，取第一个
  if (matchKeys?.length >= 1) {
    const matchKey = matchKeys[0];
    return dynamicViewsModules[matchKey];
  }
  return Error404;
}
